using System;
using System.Collections;
using System.Globalization;
using System.Reflection;
using System.Resources;
using EnvDTE;
using Microsoft.VisualStudio.CommandBars;
using NUnitGenAddIn.Core;
using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;

namespace NUnitGenAddIn.VS2005
{
    /// <summary>
    /// Visual Studio 2005 Add-In Helper
    /// </summary>
	public class VS2005AddInHelper : AddInHelper
	{
        /// <summary>
        /// Initializes a new instance of the <see cref="VS2005AddInHelper"/> class.
        /// </summary>
        /// <param name="applicationObject">The application object.</param>
        /// <param name="addInInstance">The add in instance.</param>
		public VS2005AddInHelper(DTE applicationObject, AddIn addInInstance) : base(applicationObject, addInInstance)
		{}

        /// <summary>
        /// Gets the code element list from point.
        /// </summary>
        /// <param name="currentPoint">The current point.</param>
        /// <returns>Array List</returns>
		public override ArrayList GetCodeElementListFromPoint(TextPoint currentPoint)
		{
			ArrayList codeElements = new ArrayList();
			FileCodeModel fileCodeModel = GetCodeModel4CurrentProjectItem();

			if (fileCodeModel != null)
			{
				foreach (vsCMElement scope in Enum.GetValues(typeof (vsCMElement)))
				{
					CodeElement codeElement = null;
					try
					{
						codeElement = fileCodeModel.CodeElementFromPoint(currentPoint, scope);
					}
					catch
					{}

					if (codeElement != null)
					{
					    codeElements.Add(codeElement);
					}
				}
			}
			return codeElements;
		}

        /// <summary>
        /// Gets the code class from code elements.
        /// </summary>
        /// <param name="codeElements">The code elements.</param>
        /// <returns><see cref="CodeClass"/> object</returns>
		public override CodeClass GetCodeClassFromCodeElements(CodeElements codeElements)
		{
			foreach (CodeElement element in codeElements)
			{
			    if (element.Kind == vsCMElement.vsCMElementClass)
			    {
			        return element as CodeClass;
			    }
			
                if (element.Children.Count > 0)
			    {
			        CodeClass returnedElement = GetCodeClassFromCodeElements(element.Children);
			        if (returnedElement != null)
			            return returnedElement;
			    }
			}
            return null;
		}

        /// <summary>
        /// Adds the command.
        /// </summary>
        /// <param name="commandName">Name of the command.</param>
        /// <param name="buttonText">The button text.</param>
        /// <param name="toolTip">The tool tip.</param>
        /// <param name="commandBarName">Name of the command bar.</param>
		protected override void AddCommand(string commandName, string buttonText, string toolTip, string commandBarName)
		{
			CommandBar commandBar = getTargetCommandBar(commandBarName);
			try
			{
				object[] contextGuids = new object[] {};
				//Add a command to the Commands collection:
				Command command =
					_applicationObject.Commands.AddNamedCommand(_addInInstance, commandName, buttonText, toolTip, true, 59,
					                                           ref contextGuids,
					                                           (int) vsCommandStatus.vsCommandStatusSupported +
					                                           (int) vsCommandStatus.vsCommandStatusEnabled);
				//, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
				if (commandBar != null)
					command.AddControl(commandBar, 2);
			}
			catch (Exception)
			{
			}
		}

        /// <summary>
        /// Gets the target command bar.
        /// </summary>
        /// <param name="commandBarName">Name of the command bar.</param>
        /// <returns><see cref="CommandBar"/> object</returns>
		private CommandBar getTargetCommandBar(string commandBarName)
		{
			return getTargetCommandBar(commandBarName, "");
		}

        /// <summary>
        /// Gets the target command bar.
        /// </summary>
        /// <param name="commandBarName">Name of the command bar.</param>
        /// <param name="subMenuName">Name of the sub menu.</param>
        /// <returns><see cref="CommandBar"/> object</returns>
		private CommandBar getTargetCommandBar(string commandBarName, string subMenuName)
		{
			//Place the command on the tools menu.
			//Find the MenuBar command bar, which is the top-level command bar holding all the main menu items:
			CommandBar menuBarCommandBar = ((CommandBars) _applicationObject.CommandBars)[commandBarName];
			CommandBar targetCommandBar = menuBarCommandBar;

			if (!string.IsNullOrEmpty(subMenuName))
			{
				//Find the Tools command bar on the MenuBar command bar:
				CommandBarControl toolsControl = menuBarCommandBar.Controls[getLocalizedMenuName(subMenuName)];
				CommandBarPopup toolsPopup = (CommandBarPopup) toolsControl;
				targetCommandBar = toolsPopup.CommandBar;
			}
			return targetCommandBar;
		}

        /// <summary>
        /// Gets the name of the localized menu.
        /// </summary>
        /// <param name="menuName">Name of the menu.</param>
        /// <returns>string value</returns>
		private string getLocalizedMenuName(string menuName)
		{
			string toolsMenuName;
			try
			{
				//If you would like to move the command to a different menu, change the word "Tools" to the 
				//  English version of the menu. This code will take the culture, append on the name of the menu
				//  then add the command to that menu. You can find a list of all the top-level menus in the file
				//  CommandBar.resx.
				ResourceManager resourceManager =
					new ResourceManager(_addInInstance.ProgID + ".CommandBar", Assembly.GetExecutingAssembly());
				CultureInfo cultureInfo = new CultureInfo(_applicationObject.LocaleID);

				toolsMenuName = resourceManager.GetString(String.Concat(cultureInfo.TwoLetterISOLanguageName, menuName));
			}
			catch
			{
				//We tried to find a localized version of the word Tools, but one was not found.
				//  Default to the en-US word, which may work for the current culture.
				toolsMenuName = "Tools";
			}
			return toolsMenuName;
		}
	}
}